home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1998 May / macformat-063.iso / mac / Shareware Plus / Development / ListBox 0.4 / ListBox.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-02-16  |  9.3 KB  |  461 lines  |  [TEXT/CWIE]

  1. #include "ListBox.h"
  2.  
  3. #define kScrollBarWidth        16
  4. #define kItemSize            18        //the vertical size of a cell
  5.                                     //Change this If you use different sized fonts
  6.  
  7. #define kDoubleClickTime    25        //Wait time between clicks 
  8.  
  9. //curBox is set to the current listbox before localScoll is called
  10. //localScroll is called by TrackControl, a macOS call, so I have to 
  11. //use the global to pass information to it...
  12. ListBox        *curBox;    
  13. pascal void localScroll(ControlHandle theControl, short thePart);     
  14.  
  15. ListBox::ListBox()        //This just sets everything to nil so we know that it hasn't been preped
  16. {
  17. items = nil;
  18. theScrollBar = nil;
  19. destDialog = nil;
  20. SetRect(&destRect,0,0,0,0);
  21. itemSize.v = itemSize.h = 0;
  22. topLine = 0;
  23. curLine = 0;
  24. lastClick = 0;
  25. }
  26.  
  27. ListBox::~ListBox(void)
  28. {
  29. Close();
  30. }
  31.  
  32. void ListBox::Close(void)
  33. {
  34. KillItemList();
  35. if (theScrollBar != nil)
  36.     DisposeControl(theScrollBar);
  37. theScrollBar = nil;
  38. destDialog = nil;
  39. SetRect(&destRect,0,0,0,0);
  40. itemSize.v = itemSize.h = 0;
  41. topLine = 0;
  42. curLine = 0;
  43. lastClick = 0;
  44. }
  45.  
  46.  
  47.  
  48. void ListBox::SetupFromItem(DialogPtr theDialog, short itemNum)
  49. {
  50. short    kind;
  51. Handle    dialogItem;
  52. Rect    tempRect;
  53.  
  54. destDialog  = theDialog;
  55. GetDialogItem(destDialog, itemNum, &kind, &dialogItem, &tempRect);
  56. SetupFromRect(theDialog, &tempRect);
  57. }
  58.  
  59.  
  60. void ListBox::SetupFromRect(DialogPtr theDialog, Rect *rect)
  61. {
  62. Rect    scrollRect;
  63.  
  64.  
  65. destRect = *rect;
  66. scrollRect.top = destRect.top;
  67. scrollRect.bottom = destRect.bottom;
  68. scrollRect.left = destRect.right - kScrollBarWidth;
  69. scrollRect.right = destRect.right;
  70.  
  71. theScrollBar = NewControl(destDialog,        //owningWindow
  72.                     &scrollRect,            //boundsRect
  73.                     "\p",                    //controlTitle
  74.                     true,                    //initiallyVisible
  75.                     0,                        //initialValue
  76.                     0,                        //minimumValue
  77.                     0,                        //maximumValue
  78.                     scrollBarProc,            //procID
  79.                     nil);                    //controlReference
  80. items = nil;                    
  81. itemSize.h = destRect.right - destRect.left;
  82. itemSize.v = kItemSize;
  83. topLine = 0;
  84. curLine = 0;
  85.  
  86. AdjustScrollBar();
  87. }
  88.  
  89.  
  90.  
  91. void ListBox::ModalDialog(customModalFilter modalFilter, DialogItemIndex * itemHit)
  92. {
  93. EventRecord        theEvent;
  94. short            kind;
  95. Handle            dialogItem;
  96. Rect            box;
  97. Point            thePoint;
  98.  
  99.  
  100. do{
  101.     *itemHit = 0;
  102.     GetNextEvent( everyEvent, &theEvent );
  103.     if (theEvent.what == updateEvt ) {
  104.         BeginUpdate(destDialog);
  105.         SetPort(destDialog);
  106.         DrawDialog(destDialog);
  107.         GetDialogItem(destDialog, 1, &kind, &dialogItem, &box);
  108.         InsetRect(&box, -4, -4);
  109.         PenSize(3, 3);
  110.         FrameRoundRect(&box, 15, 15);
  111.         EndUpdate(destDialog);
  112.         Draw();
  113.     }
  114.     if ( DialogSelect(&theEvent, &destDialog, itemHit) ) {
  115.         if (modalFilter != nil)
  116.             modalFilter(destDialog, &theEvent, itemHit);
  117.     }
  118.     if (TrackEvent(&theEvent)) *itemHit = 1;    //TrackEvent returns true if they double click
  119.  
  120. } while (*itemHit == -1);
  121.  
  122. }
  123.  
  124.  
  125. Boolean ListBox::TrackEvent(EventRecord *theEvent)
  126. {
  127. Point                thePoint;
  128. Rect                boxRect;
  129. short                thePart, vertLoc, newLine;
  130. ControlActionUPP     theAction = NewControlActionProc(localScroll);
  131. ControlHandle        tempControl;
  132. Boolean                doubleClick = false;
  133.  
  134. if (theEvent->what == mouseDown) {
  135.     SetPort(destDialog);
  136.     thePoint = theEvent->where;
  137.     GlobalToLocal(&thePoint);
  138.     if (PtInRect(thePoint, &destRect)) {
  139.         thePart = FindControl(thePoint, destDialog, &tempControl);
  140.         if ( tempControl == theScrollBar && thePart ) {
  141.             curBox = this;
  142.             switch ( thePart ) {
  143.                 case kControlUpButtonPart:
  144.                 case kControlDownButtonPart:
  145.                 case kControlPageUpPart:
  146.                 case kControlPageDownPart:
  147.                     thePart = TrackControl(theScrollBar, thePoint, theAction);
  148.                     break;
  149.                 case kControlIndicatorPart:
  150.                     thePart = TrackControl(theScrollBar, thePoint, nil);
  151.                     SetTopLine( GetControlValue(theScrollBar) );
  152.                     Draw();
  153.                     break;
  154.             }
  155.         }
  156.     }
  157.     boxRect = destRect;
  158.     boxRect.right -= kScrollBarWidth;
  159.     if (PtInRect(thePoint, &boxRect) ) {
  160.         vertLoc = thePoint.v - destRect.top;
  161.         newLine = vertLoc / itemSize.v;
  162.         newLine += GetTopLine();
  163.         if (newLine < GetItemCount()) {
  164.             if (newLine == GetCurLine() ) {
  165.                 if ( lastClick + kDoubleClickTime > TickCount() )
  166.                     doubleClick = true;
  167.                 lastClick = TickCount();
  168.             } else
  169.             SetCurLine(newLine);
  170.         }
  171.     }
  172. }
  173.     
  174. DisposeRoutineDescriptor(theAction);
  175. return doubleClick;
  176. }
  177.  
  178. void ListBox::SetTopLine(short line) 
  179. {
  180. topLine = line;
  181. Draw();
  182. }
  183.  
  184. short ListBox::GetTopLine(void)
  185. {
  186. return topLine;
  187. }
  188.  
  189.  
  190. short ListBox::GetCurLine(void)
  191. {
  192. return curLine;
  193. }
  194.  
  195. short ListBox::GetCurItem(void)
  196. {
  197. short    tempLine;
  198. lbItem    *curItem;
  199.  
  200. curItem = items;
  201. tempLine = 0;
  202. while (tempLine != GetCurLine() && curItem != nil) {
  203.     curItem = curItem->next;
  204.     tempLine++;
  205. }
  206. return curItem->idNum;
  207. }
  208.  
  209. void ListBox::SetCurLine(short line)
  210. {
  211. curLine = line;
  212. Draw();
  213. }
  214.  
  215.  
  216. void ListBox::AdjustScrollBar(void)
  217. {
  218. short    newMax;
  219. newMax = GetItemCount() - ((destRect.bottom - destRect.top) / itemSize.v);
  220. if (newMax < 0)
  221.     newMax = 0;
  222. SetControlMaximum( theScrollBar, newMax);
  223. SetControlValue( theScrollBar, GetTopLine());
  224. Draw1Control(theScrollBar);
  225. }
  226.  
  227. void ListBox::Draw(void)
  228. {
  229. RGBColor    white = {0xff, 0xff, 0xff},
  230.             black = {0x00, 0x00, 0x00},
  231.             tempColor;
  232. short        tempLine, bottomLine, charSize, i, selectedLine = GetCurLine();
  233. lbItem        *curItem;
  234. Point        curPoint;
  235. Rect        tempRect;
  236.  
  237. SetPort(destDialog);
  238.  
  239. GetForeColor(&tempColor);
  240.  
  241. tempRect = destRect;
  242. tempRect.right -= kScrollBarWidth;
  243. EraseRect(&tempRect);
  244.  
  245. tempRect.right++;
  246. PenSize(1,1);
  247. RGBForeColor(&black);
  248. FrameRoundRect(&tempRect,1,1);
  249.  
  250. curItem = items;
  251. tempLine = 0;
  252. while (tempLine != GetTopLine() && curItem != nil) {
  253.     curItem = curItem->next;
  254.     tempLine++;
  255. }
  256.  
  257. bottomLine = (destRect.bottom - destRect.top) / itemSize.v + GetTopLine();
  258. while (tempLine < bottomLine && curItem != nil) {
  259.     curPoint.v = (tempLine - GetTopLine() + 1) * itemSize.v + destRect.top - 4;
  260.     curPoint.h = 5 + destRect.left;
  261.     MoveTo(curPoint.h, curPoint.v);
  262.     
  263.     i = 1;
  264.     charSize = kScrollBarWidth;
  265.     while (charSize < itemSize.h && i <= curItem->name[0]) { 
  266.         DrawChar(curItem->name[i]);
  267.         charSize += CharWidth(curItem->name[i]);
  268.         i++;
  269.     };
  270.     
  271.     
  272.     if (tempLine == selectedLine) {
  273.         tempRect.top = (tempLine - GetTopLine() ) * itemSize.v + destRect.top + 1;
  274.         tempRect.bottom = (tempLine - GetTopLine() + 1) * itemSize.v + destRect.top - 1;
  275.         tempRect.left = destRect.left + 1;
  276.         tempRect.right = destRect.right - kScrollBarWidth;
  277.         InvertRect(&tempRect);
  278.     }
  279.     tempLine++;
  280.     curItem = curItem->next;
  281. }
  282. RGBForeColor(&tempColor);
  283. Draw1Control(theScrollBar);
  284. }
  285.  
  286.  
  287. void ListBox::MakeResTypeList(long resType)
  288. {
  289. int        resCount, i;
  290. Str255    name;
  291. Handle    handle;
  292. short    dummyID;
  293. ResType    dummyType;
  294.  
  295. resCount = Count1Resources(resType);
  296. for (i = 0; i < resCount; i++) {
  297.     handle = Get1IndResource(resType, i + 1);
  298.     if (handle) {
  299.         GetResInfo(handle, &dummyID, &dummyType, name);
  300.         if (name[0] > 0)
  301.             AddItem(dummyID, name);
  302.         else {
  303.             NumToString(dummyID, &name[0]);
  304.             AddItem(dummyID, name);
  305.         }
  306.         ReleaseResource(handle);
  307.     }
  308. }
  309. }
  310.  
  311.  
  312. void ListBox::AddItem(short idNum, Str255 name)
  313. {
  314. lbItem    *curItem;
  315. short    i;
  316.  
  317. if (items == nil) {
  318.     items = (lbItem *) NewPtrClear(sizeof(lbItem));
  319.     curItem = items;
  320. } else {
  321.     curItem = items;
  322.     while (curItem->next != nil)
  323.         curItem = curItem->next;
  324.  
  325.     curItem->next = (lbItem *)NewPtrClear(sizeof(lbItem));
  326.     curItem = curItem->next;
  327. }
  328.  
  329. if (curItem != nil) {
  330.     curItem->idNum = idNum;
  331.     for (i = 0; i < 255; i++)
  332.         curItem->name[i] = name[i];
  333.     curItem->next = nil;
  334. }
  335.  
  336. AdjustScrollBar();
  337. }
  338.  
  339.  
  340. void ListBox::SwapLines(short line1, short line2)
  341. {
  342. short    tempLine, i, tempID;
  343. lbItem    *item1, *item2;
  344. Str255    tempStr;
  345.  
  346. item1 = items;
  347. tempLine = 0;
  348. while (tempLine != line1 && item1 != nil) {
  349.     item1 = item1->next;
  350.     tempLine++;
  351. }
  352. item2 = items;
  353. tempLine = 0;
  354. while (tempLine != line2 && item2 != nil) {
  355.     item2 = item2->next;
  356.     tempLine++;
  357. }
  358.  
  359. if (item1 == nil || item2 == nil)
  360.     return;
  361.  
  362. for (i=0; i < 255; i++)
  363.     tempStr[i] = item1->name[i];
  364. for (i=0; i < 255; i++)
  365.     item1->name[i] = item2->name[i];
  366. for (i=0; i < 255; i++)
  367.     item2->name[i] = tempStr[i];
  368.     
  369. tempID = item1->idNum;
  370. item1->idNum = item2->idNum;
  371. item2->idNum = tempID;    
  372. }
  373.  
  374.  
  375. void ListBox::KillLine(short num)
  376. {
  377. lbItem     *curItem, *tempItem;
  378. short    tempLine;
  379.  
  380. if (items == nil)
  381.     return;
  382.  
  383. if (num == 0) {
  384.     tempItem = items;
  385.     items = tempItem->next;
  386.     DisposePtr( (Ptr) tempItem);
  387. } else {
  388.     tempLine = 0;
  389.     curItem = items;
  390.     while (curItem != nil && tempLine != num - 1 ) {
  391.         curItem = curItem->next;
  392.         tempLine++;
  393.     }
  394.     
  395.     if (curItem != nil ) {
  396.         tempItem = curItem->next;
  397.         curItem->next = tempItem->next;
  398.         DisposePtr( (Ptr) tempItem);
  399.     }
  400. }
  401. }
  402.  
  403.  
  404. void ListBox::KillItemList(void)
  405. {
  406. lbItem     *curItem, *curItem2;
  407.  
  408. curItem2 = items;
  409.  
  410. while (curItem2 != nil) {
  411.     curItem = curItem2;
  412.     curItem2 = curItem2->next;
  413.     DisposePtr((Ptr)curItem);
  414. }
  415. items = nil;
  416. }
  417.  
  418.  
  419. short ListBox::GetItemCount(void)
  420. {
  421. short     count = 0;
  422. lbItem    *curItem = items;
  423.  
  424. while (curItem != nil) {
  425.     curItem = curItem->next;
  426.     count++;
  427. }
  428. return count;
  429. }
  430.  
  431. pascal void localScroll(ControlHandle theControl, short thePart)
  432. {
  433. short delta;
  434. short oldValue;
  435.  
  436. if ( theControl != curBox->theScrollBar)
  437.     return;
  438.  
  439. switch ( thePart ) {
  440.     case kControlUpButtonPart: 
  441.         delta = -1;break;
  442.     case kControlDownButtonPart: 
  443.         delta = 1;break;
  444.     case kControlPageUpPart: 
  445.         delta = -5;break;
  446.     case kControlPageDownPart: 
  447.         delta = 5;break;
  448. }
  449. if ( thePart != 0 ) {
  450.     oldValue = GetControlValue(theControl);
  451.     SetControlValue(theControl , oldValue + delta);
  452.     if (oldValue + delta >= GetControlMaximum(theControl))
  453.         SetControlValue(theControl, GetControlMaximum(theControl));
  454.     if (oldValue + delta <= GetControlMinimum(theControl))
  455.         SetControlValue(theControl, GetControlMinimum(theControl));
  456.     if (oldValue != GetControlValue(theControl)) {
  457.         curBox->SetTopLine( GetControlValue(theControl) );
  458.         curBox->Draw();
  459.     }
  460. }
  461. }